using System;
using System.Text;
using System.Collections.Generic;
using InfoJetSoft.Service.XPath;

//CID 0164 //2008.12.13 //Begin
namespace InfoJetSoft.Service.XPath.Exprs
{
	/// <summary>
	/// Summary description for AdditiveExpr.
	/// </summary>
    class AdditiveExpr : IExpr
	{
        private List<IExpr> multiplicateList = null;

		public AdditiveExpr()
		{
			//
			// TODO: Add constructor logic here
			//
        }

        public object Evaluate(ExprContext context)
        {
            //CID 0795 //2011.02.18 //Begin
            object leftValue = null;
            for (int i = 0; i < this.multiplicateList.Count; i++)
            {
                IExpr expr = this.multiplicateList[i];
                if (expr is OperatorExpr)
                {
                    OperatorExpr oper = (OperatorExpr)expr;
                    i++;
                    IExpr nextExpr = this.multiplicateList[i];
                    object rightValue = nextExpr.Evaluate(context);
                    if (oper.Operator == Operator.Add)
                    {
                        leftValue = this.Add(context, leftValue, rightValue);
                    }
                    else if (oper.Operator == Operator.Subtract)
                    {
                        leftValue = this.Subtract(context, leftValue, rightValue);
                    }
                    else
                    {
                        throw new Exception("Unsupported operator: " + oper.Operator);
                    }
                }
                else
                {
                    if (leftValue == null)
                    {
                        leftValue = expr.Evaluate(context);
                    }
                    else
                    {
                        throw new Exception("Unsupported expr order");
                    }
                }
            }
            return leftValue;
            //CID 0795 //2011.02.18 //End
        }

        //CID 0866 //2011.04.01 //Begin
        public void Visit(IExprVisitor visitor)
        {
            for (int i = 0; i < this.multiplicateList.Count; i++)
            {
                IExpr expr = this.multiplicateList[i];
                expr.Visit(visitor);
            }
        }
        //CID 0866 //2011.04.01 //End

        //CID 0795 //2011.02.25 //Begin
        private object Add(ExprContext context, object value1, object value2)
        {
            double number1 = NumberFunctions.number(context, value1);
            double number2 = NumberFunctions.number(context, value2);
            if (double.IsNaN(number1) || double.IsNaN(number2))
            {
                return double.NaN;
            }
            else
            {
                return number1 + number2;
            }
        }
        //CID 0795 //2011.02.25 //End

        //CID 0795 //2011.02.25 //Begin
        private object Subtract(ExprContext context, object value1, object value2)
        {
            double number1 = NumberFunctions.number(context, value1);
            double number2 = NumberFunctions.number(context, value2);
            if (double.IsNaN(number1) || double.IsNaN(number2))
            {
                return double.NaN;
            }
            else
            {
                return number1 - number2;
            }
        }
        //CID 0795 //2011.02.25 //End

        public void Print(StringBuilder buffer)
        {
            foreach (IExpr expr in this.multiplicateList)
            {
                expr.Print(buffer);
            }
        }

        public static IExpr Parse(ExprParser parser)
		{
			IExpr multiplicateExpr = MultiplicativeExpr.Parse( parser );
			if( multiplicateExpr != null )
			{
                List<IExpr> list = new List<IExpr>();
				list.Add( multiplicateExpr );

                OperatorExpr additiveOperator = OperatorExpr.ParseAdditiveOperator(parser);
				while( additiveOperator != null )
				{
					list.Add( additiveOperator );

                    IExpr nextMultiplicativeExpr = MultiplicativeExpr.Parse(parser);
					if( nextMultiplicativeExpr == null )
					{
						throw new Exception( "Cannot parse " + parser.XPath );
					}
					list.Add( nextMultiplicativeExpr );
					
					additiveOperator = OperatorExpr.ParseAdditiveOperator( parser );
				}

                if (list.Count > 1)
                {
                    AdditiveExpr additiveExpr = new AdditiveExpr();
                    additiveExpr.multiplicateList = list;
                    return additiveExpr;
                }
                else
                {
                    return multiplicateExpr;
                }
			}
			return null;
		}
	}
}
//CID 0164 //2008.12.13 //End
